#include "sio.h" #include <varargs.h> int Sread( fd, buf, nbytes ) int fd ; char *buf ; int nbytes ; int Sgetc( fd ) int fd ; char *Srdline( fd ) int fd ; char *Sfetch( fd, length ) int fd ; long *length ; int Swrite( fd, buf, nbytes ) int fd ; char *buf ; int nbytes ; int Sputc( fd, c ) int fd ; char c ; int Sprint( fd, format [ , ... ] ) int fd ; char *format ; int Sprintv( fd, format, ap ) int fd ; char *format ; va_list ap ; int Sdone( fd ) int fd ; int Sundo( fd, type ) int fd ; int type ; int Stie( ifd, ofd ) int ifd, ofd ; int Suntie( fd ) int fd ; int Sbuftype( fd, type ) int fd, type ; int Smorefds() int Sflush( fd ) int fd ; int Sclose( fd ) int fd ; int Sgetchar( fd ) int fd ; int Sputchar( fd, c ) int fd; char c ; int SIOLINELEN( fd ) int fd ; int SIOMAXLINELEN( fd ) int fd ;
I/O operations on different file descriptors do not interfere (unless the file descriptors refer to the same file, in which case the results are undefined).
For disk files I/O always starts at the current file offset. If that offset is not a multiple of the preferred block size for file system I/O (the st_blksize field in struct stat), performance will not be optimal. For optimal performance, it is recommended that no I/O operations (like read(2) or write(2)) are applied to the file descriptor if it is to be used by SIO.
Read I/O is either buffered or is done using memory mapping whenever that is possible and appropriate.
The library functions that do stream I/O resemble system calls (for example Sread() resembles read(2)) so that modifying a program that uses the system calls to use the SIO functions is easy (e.g. just replace read(2) with Sread(); the function signatures as well as the return values are exactly the same).
Sread() reads nbytes bytes from the stream associated with file descriptor fd into the buffer pointed to by buf.
Sgetc() reads a character from the stream associated with file descriptor fd. It returns SIO_EOF if the end of file has been reached.
Sgetchar() (a macro) performs exactly the same function as Sgetc() but it is much faster.
Srdline() reads a line from the stream associated with file descriptor fd. The newline at the end of the line is replaced by a 0 byte. Lines longer than the maximum line length supported by SIO will have characters deleted.
SIOLINELEN() (a macro) returns the length of the line returned by the last call to Srdline() (the value returned by SIOLINELEN() is valid only after Srdline() and as long as no other SIO calls are performed on that file descriptor).
SIOMAXLINELEN() (a macro) returns the maximul line length supported by SIO for the file descriptor. As a side-effect it initializes fd for input.
Sfetch() returns a pointer to data coming from the stream associated with file descriptor fd. The amount of data available is indicated by the length argument. One possible use for this function is copying of files.
Swrite() writes nbytes bytes to the stream associated with file descriptor fd from the buffer pointed to by buf.
Sputc() writes a single character to the stream associated with file descriptor fd.
Sputchar() (a macro) performs exactly the same function as Sputc() but it is much faster.
Sprint() imitates the behavior of printf(3) as defined in the ANSI C Standard. There are some limitations. Check the Sprint() man page for more information.
Sprintv() is the same as Sprint() except that it takes a varargs argument list.
Sundo() returns the characters returned by the last call to Srdline(), Sgetc() or Sgetchar() to the stream so that they can be reread. The type argument to Sundo() can be SIO_UNDO_LINE or SIO_UNDO_CHAR depending on whether the call whose effect needs to be undone was Srdline() or Sgetc()/Sgetchar() respectively. There is no check on whether the last function invoked on fd was one of the above and the results are undefined if there is no correspondence between the type and the last operation on fd. (i.e. the result is undefined if you try SIO_UNDO_CHAR and the last operation was not Sgetchar() or Sgetc()).
Stie() ties the file descriptor ifd to the file descriptor ofd. This means that whenever a read(2) is done on ifd, it is preceded by a write(2) on ofd. For filters it is useful to do Stie( 0, 1 ) to maximize concurrency. It is also useful to do the same thing when you issue prompts to the user and you want the user reply to appear on the same line with the prompt. ifd, ofd will be initialized for input, output respectively (if any of them is initialized, it must be for the appropriate stream type (input or output)). If ifd was tied to another file descriptor, the old tie is broken.
Suntie() undoes the effect of Stie() for the specified input file descriptor.
Sbuftype() determines the buffering type for the output stream associated with file descriptor fd. By default output directed to terminals is line buffered, output directed to file descriptor 2 (standard error) is unbuffered and everything else is fully buffered. Possible values for the type argument are
Smorefds() should be used to inform SIO that the number of available file descriptors has been increased. SIO uses an array of internal stream descriptors which are indexed by the file descriptor number. Some operating systems (ex. SunOS 4.1[.x]) allow the number of available file descriptors to vary. If that number is increased beyond its initial value SIO needs to know in order to allocate more stream descriptors.
Sdone() flushes any buffered output for fd and releases the SIO resources used. Sdone() is useful in case the program needs to reprocess the data of a file descriptor (assuming the file descriptor corresponds to a file). The program can call Sdone(), lseek(2) to the beginning of the file and then proceed to reread the file.
Sflush() causes any buffered stream output to be written to the file descriptor. If its argument is the special value SIO_FLUSH_ALL then all output streams will be flushed.
Sclose() closes a file descriptor used for stream I/O, flushes any buffered output and releases the SIO resources used.
The following code implements a (poor) substitute for the tee command (it copies standard input to a file as well as to standard output).
#include "sio.h" main( argc, argv ) int argc ; char *argv[] ; { char *file = (argc > 1) ? argv[ 1 ] : "tee.file" ; int fd = creat( file, 0644 ) ; long length ; char *s ; while ( s = Sfetch( 0, &length ) ) { Swrite( 1, s, length ) ; Swrite( fd, s, length ) ; } exit( 0 ) ; }
Sread() returns the number of bytes read on success (0 means end-of-file) or SIO_ERR on failure (errno is set to indicate the error).
Sgetc() returns the character read on success, SIO_EOF when the end-of-file is reached, or SIO_ERR on failure (errno is set to indicate the error).
Srdline() returns a pointer to the next line on success. On failure or when the end-of-file is reached it returns NULL. If the end-of-file is reached errno is set to 0, otherwise it indicates the error.
Sfetch() returns a pointer to file data on success. (the length argument indicates how many bytes are available). On failure or when the end-of-file is reached it returns NULL. If the end-of-file is reached errno is set to 0, otherwise it indicates the error.
Swrite() returns the number of bytes written on success or SIO_ERR on failure (errno is set to indicate the error).
Sputc() returns the character it was given as an argument on success Sprint() returns the number of characters printed on success or SIO_ERR on failure (errno is set to indicate the error).
Sdone() returns 0 on success or SIO_ERR on failure (errno is set to indicate the error).
Sundo() returns 0 on success or SIO_ERR on failure (errno is set to indicate the error).
Stie() returns 0 on success or SIO_ERR on failure (errno is set to indicate the error).
Suntie() returns 0 on success or SIO_ERR on failure (errno is set to EBADF if there was no tied file descriptor).
Sbuftype() returns 0 on success or SIO_ERR on failure (errno is set to EBADF if this is not an output stream or to EINVAL if an unknown type is specified).
Smorefds() returns 0 on success or SIO_ERR on failure (because of lack of memory).
Sflush() returns 0 on success or SIO_ERR on failure (errno is set to indicate the error).
Sclose() returns 0 on success or SIO_ERR on failure (errno is set to indicate the error).
Sgetchar() returns the character read on success, SIO_EOF when the end-of-file is reached, or SIO_ERR on failure (errno is set to indicate the error).
Sputchar() returns the character it was given as an argument on success or SIO_ERR on failure (errno is set to indicate the error).
SIOLINELEN() returns the length of the last line read by Srdline().
SIOMAXLINELEN() returns the length of the longest line supported by SIO on success or SIO_ERR on failure (errno is set to indicate the error).
Attempting a read operation on a descriptor opened for writing or vice versa will cause the operation to fail with errno set to EBADF.
The first SIO operation on a descriptor must be a read or write operation. It cannot be a control operation (like Sflush()). Such an operation will fail with errno set to EBADF.
Sprint(3)
If the operating system does not provide for invocation of a finalization function upon exit, the program will have to explicitly flush all output streams. The following operating systems provide such a facility: SunOS 4.x, Ultrix 4.x.
Socket file descriptors can be used for input as well as output but SIO does not support this.
The current implementation will not try to use memory mapping to read a file if the file offset is not 0 (it will use buffered I/O instead).
Pointers returned by Sfetch() point to read-only memory. Attempting to modify this memory will result in a segmentation violation.